﻿//==============================================================
//  Create by whl at 4/11/2014 10:49:10 AM.
//  Version 1.0
//  
//==============================================================


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cn.Finder.SDKFramework.Response;
using System.Xml.Serialization;
using System.Text.RegularExpressions;
using System.IO;

namespace Cn.Finder.SDKFramework.Parser
{
    /// <summary>
    /// XML 解析器
    /// </summary>
    public class XmlParser:IParser
    {
        // Fields
        private static Dictionary<string, XmlSerializer> parsers;
        private static Regex regex;

      
        public XmlParser()
        {
            regex = new Regex(@"<(\w+?)[ >]", RegexOptions.Compiled);
            parsers = new Dictionary<string, XmlSerializer>();
        }
        private string GetRootElement(string body)
        {
            Match match = regex.Match(body);
            if (!match.Success)
            {
                throw new ApiException("Invalid XML response format!");
            }
            return match.Groups[1].ToString();

        }

        public T Parse<T>(string body) where T : ApiResponse
        {
            Type type = typeof(T);
            string rootElement = this.GetRootElement(body);
            string fullName = type.FullName;
            if ("error_response".Equals(rootElement))
            {
                fullName = fullName + "_error_response";
            }
            XmlSerializer serializer = null;
            if (!parsers.TryGetValue(fullName, out serializer) || (serializer == null))
            {
                XmlAttributes attributes = new XmlAttributes
                {
                    XmlRoot = new XmlRootAttribute(rootElement)
                };
                XmlAttributeOverrides overrides = new XmlAttributeOverrides();
                overrides.Add(type, attributes);
                serializer = new XmlSerializer(type, overrides);


                parsers[fullName] = serializer;
            }
            object respTmp = null;
            using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(body)))
            {
                respTmp = serializer.Deserialize(stream);
            }
            T resp = (T)respTmp;
            if (resp != null)
            {
                resp.Body = body;
            }
            return resp;

        }
    }
}
